﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.SharePoint;
using Chaks.SharePoint.Docs.ILP.Utilities;

namespace Chaks.SharePoint.Docs.ILP.EventReceivers
{
    public class DocumentLibraryEventReceiver : SPItemEventReceiver
    {
        #region ItemAdding

        /// <summary>
        /// Synchronous before event that occurs when a new item is added to its containing object.
        /// </summary>
        /// <param name="properties">An <see cref="T:Microsoft.SharePoint.SPItemEventProperties"></see> object that represents properties of the event handler.</param>
        public override void ItemAdding(SPItemEventProperties properties)
        {
            System.Diagnostics.Debug.WriteLine("ScheduleListEventReceiver.ItemAdding(): begin");

            try
            {
                DisableEventFiring();
                //TODO: do stuff!
                base.ItemAdding(properties);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine("ScheduleListEventReceiver.ItemAdded() exception" + ex);

            }
            finally
            {
                EnableEventFiring();
            }

            System.Diagnostics.Debug.WriteLine("ScheduleListEventReceiver.ItemAdding(): end");
        }

        #endregion

        #region ItemAdded

        /// <summary>
        /// Asynchronous After event that occurs after a new item has been added to its containing object.
        /// </summary>
        /// <param name="properties">An <see cref="T:Microsoft.SharePoint.SPItemEventProperties"></see> object that represents properties of the event handler.</param>
        public override void ItemAdded(SPItemEventProperties properties)
        {
            System.Diagnostics.Debug.WriteLine("ScheduleListEventReceiver.ItemAdded(): begin");

            try
            {
                DisableEventFiring();
                
                SetItemLevelPermission(properties);

                base.ItemAdded(properties);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine("ScheduleListEventReceiver.ItemAdded() exception" + ex);
            }
            finally
            {
                EnableEventFiring();
            }

            System.Diagnostics.Debug.WriteLine("ScheduleListEventReceiver.ItemAdded(): end");
        }

        #endregion

        #region ItemUpdating

        /// <summary>
        /// Synchronous before event that occurs when an existing item is changed, for example, when the user changes data in one or more fields.
        /// </summary>
        /// <param name="properties">An <see cref="T:Microsoft.SharePoint.SPItemEventProperties"></see> object that represents properties of the event handler.</param>
        public override void ItemUpdating(SPItemEventProperties properties)
        {
            System.Diagnostics.Debug.WriteLine("ScheduleListEventReceiver.ItemUpdating(): begin");

            try
            {
                DisableEventFiring();
                //TODO: do stuff!
                base.ItemUpdating(properties);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine("ScheduleListEventReceiver.ItemUpdating() exception" + ex);
            }
            finally
            {
                EnableEventFiring();
            }

            System.Diagnostics.Debug.WriteLine("ScheduleListEventReceiver.ItemUpdating(): end");
        }

        #endregion

        #region ItemUpdated

        /// <summary>
        /// Asynchronous after event that occurs after an existing item is changed, for example, when the user changes data in one or more fields.
        /// </summary>
        /// <param name="properties">An <see cref="T:Microsoft.SharePoint.SPItemEventProperties"></see> object that represents properties of the event handler.</param>
        public override void ItemUpdated(SPItemEventProperties properties)
        {
            System.Diagnostics.Debug.WriteLine("ScheduleListEventReceiver.ItemUpdated(): begin");

            try
            {
                if (properties.AfterProperties["vti_sourcecontrolcheckedoutby"] == null && properties.BeforeProperties["vti_sourcecontrolcheckedoutby"] != null)
                {
                    //This is when the update event is triggered by check-in.
                }
                else
                {
                    DisableEventFiring();

                    SetItemLevelPermission(properties);
                    
                }
                
                base.ItemUpdated(properties);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine("ScheduleListEventReceiver.ItemUpdated() exception" + ex);
            }
            finally
            {
                EnableEventFiring();
            }

            System.Diagnostics.Debug.WriteLine("ScheduleListEventReceiver.ItemUpdated(): end");
        }

        #endregion

        private void SetItemLevelPermission(SPItemEventProperties properties)
        {
            SPSecurity.RunWithElevatedPrivileges(delegate
            {
                using (SPSite spSite = new SPSite(properties.SiteId))
                {
                    using (SPWeb curWeb = spSite.OpenWeb(properties.RelativeWebUrl))
                    {
                        //get the root web. make sure we dispose this at the end
                        SPWeb rootWeb = spSite.RootWeb;

                        //check whether we have the list id in ILPSet
                        string strListGuid = properties.ListId.ToString("B");
                        if (rootWeb.ILPExists(strListGuid))
                        {
                            //get the ILPSet Item
                            ILPSetItem ilpSetItem =
                                rootWeb.GetILPSetItem(strListGuid);

                            string[] groups =
                                ilpSetItem.Groups.Split(',');

                            //get the current list and list item
                            SPListItem curListItem = properties.ListItem;
                          
                            //break role inheritance and dont copy the permissions
                            //to all items
                            if (!curListItem.HasUniqueRoleAssignments)
                            {
                                curListItem.BreakRoleInheritance(false);
                            }

                            //get the default role definition
                            SPRoleDefinition roleDefinition = curWeb.RoleDefinitions.Cast<SPRoleDefinition>()
                                                                    .FirstOrDefault(r => r.Name == ilpSetItem.PermissionLevel);

                            //if there any such role definition exists
                            //proceed to the next step
                            if (roleDefinition != null)
                            {
                                foreach (string group in groups)
                                {
                                    //get the default sharepoint group
                                    SPGroup spGroup = curWeb.SiteGroups.Cast<SPGroup>().FirstOrDefault(g => g.Name == group);
                                    
                                    if (spGroup != null)
                                    {
                                        //create a role assignment from the group reference
                                        SPRoleAssignment roleAssignment = new SPRoleAssignment(spGroup);

                                        //update the role assignments for the group by adding the permissionSet
                                        roleAssignment.RoleDefinitionBindings.Add(roleDefinition);

                                        //apply the new roleassignment to the folder
                                        curListItem.RoleAssignments.Add(roleAssignment);
                                    }
                                }
                            }

                            curListItem.Update();
                        }

                    }
                }
            });
        }
    }

}
